﻿unit UAutoMasterDetail;

interface

uses
  Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
  Vcl.Controls, Vcl.Forms, Vcl.Dialogs, USingle, FireDAC.Stan.Intf, FireDAC.Stan.Option, FireDAC.Stan.Param,
  FireDAC.Stan.Error, FireDAC.DatS, FireDAC.Phys.Intf, FireDAC.DApt.Intf, FireDAC.Stan.Async, FireDAC.DApt, frxClass,
  frxDBSet, Data.DB, FireDAC.Comp.DataSet, Vcl.Menus, FireDAC.Comp.Client, System.ImageList, Vcl.ImgList, Vcl.DBActns,
  System.Actions, Vcl.ActnList, Vcl.ComCtrls, Vcl.ToolWin, DBGridEhGrouping, ToolCtrlsEh, DBGridEhToolCtrls,
  DynVarsEh, System.StrUtils, cxTextEdit,
  Vcl.ExtCtrls, EhLibVCL, GridsEh, DBAxisGridsEh, DBGridEh, Vcl.Buttons, Vcl.StdCtrls, Vcl.Mask, Vcl.DBCtrls,
  SearchBitBtn, Data.Win.ADODB, cxGraphics, cxControls, cxLookAndFeels,
  cxLookAndFeelPainters, cxStyles, dxSkinsCore, dxSkinsDefaultPainters,
  cxCustomData, cxFilter, cxData, cxDataStorage, cxEdit, cxNavigator, dxDateRanges, cxDBData, cxGridLevel, cxClasses,
  cxGridCustomView, cxGridCustomTableView, cxGridTableView, cxcheckbox,
  cxGridDBTableView, cxGrid, cxGridExportLink, cxPC, dxDockControl, dxDockPanel,
  cxDBLookupComboBox, cxDateUtils, cxLabel, cxCalendar, cxDBEdit,
  cxTLData, cxDBTL, Excel2000, Vcl.OleServer, cxButtonEdit, cxContainer, cxMaskEdit, cxDropDownEdit;

type
  TfrmAutoMasterDetail = class(TfrmSingle)
    dsDetail: TDataSource;
    frxDBDSDetail: TfrxDBDataset;
    PMDetailGrid: TPopupMenu;
    MenuItem1: TMenuItem;
    NLotEdit: TMenuItem;
    MenuItem2: TMenuItem;
    ActDIns: TAction;
    ActDApp: TAction;
    ActDDel: TAction;
    ActLotEdit: TAction;
    FDQryDetail: TFDQuery;
    FDUPSQLDetail: TFDUpdateSQL;
    PageControl1: TPageControl;
    TabSheet1: TTabSheet;
    Panel1: TPanel;
    pnlSearchTool: TPanel;
    sbFastFind: TSpeedButton;
    EdtLocate: TEdit;
    CmbFindField: TComboBox;
    cxGridMaster: TcxGrid;
    cxGridMasterDBTableView1: TcxGridDBTableView;
    cxGridMasterLevel1: TcxGridLevel;
    TabSheet2: TTabSheet;
    cxGridDetailDBTableView1: TcxGridDBTableView;
    cxGridDetailLevel1: TcxGridLevel;
    cxGridDetailDBTableViewColumn: TcxGridDBColumn;
    N4: TMenuItem;
    N5: TMenuItem;
    cxGridDetail: TcxGrid;
    FlowPanel1: TFlowPanel;
    FDQryinitialization: TFDQuery;
    FDQryModuleMasterSet: TFDQuery;
    procedure DBGEhMasterDblClick(Sender: TObject);
    procedure ActAddExecute(Sender: TObject);
    procedure ActEditExecute(Sender: TObject);
    procedure ActPostExecute(Sender: TObject);
    procedure ActCancelExecute(Sender: TObject);
    procedure dsMasterStateChange(Sender: TObject);
    procedure ActDInsExecute(Sender: TObject);
    procedure ActDAppExecute(Sender: TObject);
    procedure ActDDelExecute(Sender: TObject);
    procedure ActLotEditExecute(Sender: TObject);
    procedure ActExportExecute(Sender: TObject);
    procedure N4Click(Sender: TObject);
    procedure GrdDetailEditButtonClick(Sender: TObject);
    procedure FDQryMasterAfterScroll(DataSet: TDataSet);
    procedure FDQryMasterBeforeDelete(DataSet: TDataSet);
    procedure FDQryDetailNewRecord(DataSet: TDataSet);
    procedure FormShow(Sender: TObject);
    procedure cxGridMasterDBTableView1CustomDrawCell(Sender: TcxCustomGridTableView; ACanvas: TcxCanvas; AViewInfo: TcxGridTableDataCellViewInfo; var ADone: Boolean);
    procedure cxGridMasterDBTableView1CustomDrawIndicatorCell(Sender: TcxGridTableView; ACanvas: TcxCanvas; AViewInfo: TcxCustomGridIndicatorItemViewInfo; var ADone: Boolean);
    procedure cxGridDetailDBTableView1Column1PropertiesButtonClick(Sender: TObject; AButtonIndex: Integer);
    procedure cxGridDetailDBTableView1CustomDrawIndicatorCell(Sender: TcxGridTableView; ACanvas: TcxCanvas; AViewInfo: TcxCustomGridIndicatorItemViewInfo; var ADone: Boolean);
    procedure cxGridDetailDBTableView1CustomDrawCell(Sender: TcxCustomGridTableView; ACanvas: TcxCanvas; AViewInfo: TcxGridTableDataCellViewInfo; var ADone: Boolean);
    procedure cxGridMasterDBTableView1DblClick(Sender: TObject);
    procedure cxDBButtonEdit1PropertiesButtonClick(Sender: TObject; AButtonIndex: Integer);
    procedure FlowPanel1Resize(Sender: TObject);

  private
    procedure refreshMasterDisplaylabe;
    { Private declarations }
  protected

  public
    { Public declarations }

  end;

var
  frmAutoMasterDetail: TfrmAutoMasterDetail;
  SystemMouseKey: Integer;
  SelectField: string;

implementation

Uses Udm, Ucommon, USelectData;
{$R *.dfm}

procedure TfrmAutoMasterDetail.ActAddExecute(Sender: TObject);
begin
  inherited;
  PageControl1.ActivePageIndex := 1;
  if not FDQryDetail.Active then
    FDQryDetail.Open();

end;

procedure TfrmAutoMasterDetail.ActCancelExecute(Sender: TObject);
begin
  inherited;
  FDQryDetail.Cancel;
  if FDQryDetail.CachedUpdates then
    FDQryDetail.CancelUpdates;
end;

procedure TfrmAutoMasterDetail.ActDAppExecute(Sender: TObject);

begin
  if not(FDQryMaster.State in dseditmodes) then
    exit;
  inherited;
  if PMDetailGrid.PopupComponent = nil then
    exit;

  if FDQryDetail.State in dseditmodes then
    FDQryDetail.Post;
  FDQryDetail.Append;

end;

procedure TfrmAutoMasterDetail.ActDDelExecute(Sender: TObject);
ResourceString
  RaiseStr1 = '删除';
begin
  if not(FDQryMaster.State in dseditmodes) then
    exit;
  inherited;
  if PMDetailGrid.PopupComponent = nil then
    exit;

  if FDQryDetail.IsEmpty then
    abort;
  if FDQryMaster.State in dseditmodes then
    if MessageDlg(format(QuestionMSG, [RaiseStr1]), Mtinformation, [mbyes, mbno], 0) <> mryes then
      abort;
  try
    if FDQryDetail.State = dsInsert then
      FDQryDetail.Cancel
    else
    begin
      if FDQryDetail.RecordCount = 1 then
      begin
        if FDQryDetail.State = dsEdit then
          FDQryDetail.Cancel;
        FDQryDetail.First;
      end;
      if not FDQryDetail.IsEmpty then
        FDQryDetail.Delete;
    end;
  except
  end;

end;

procedure TfrmAutoMasterDetail.ActDInsExecute(Sender: TObject);
begin
  if not(FDQryMaster.State in dseditmodes) then
    exit;
  inherited;
  if PMDetailGrid.PopupComponent = nil then
    exit;

  if FDQryDetail.State in dseditmodes then
    FDQryDetail.Post
  else
    FDQryDetail.Insert;

end;

procedure TfrmAutoMasterDetail.ActEditExecute(Sender: TObject);
begin
  inherited;
  PageControl1.ActivePageIndex := 1;
  if not FDQryDetail.Active then
    FDQryDetail.Open()

end;

procedure TfrmAutoMasterDetail.ActExportExecute(Sender: TObject);
begin
  inherited;
  SaveDialog1.Filter := 'excel文件|*.xls';
  if SaveDialog1.Execute then
  begin
    if LowerCase(ExtractFileExt(SaveDialog1.FileName)) <> 'xls' then
      SaveDialog1.FileName := SaveDialog1.FileName + '.xls';
    if FileExists(SaveDialog1.FileName) then
    begin
      if application.MessageBox('该文件已经存在，是否覆盖！', '系统提示', MB_ICONASTERISK or MB_OKCANCEL) <> IDOK then
        exit;
    end;
    ExportGridToExcel(SaveDialog1.FileName, cxGridMaster);
    showmessage('保存成功！');
  end;
end;

procedure TfrmAutoMasterDetail.ActLotEditExecute(Sender: TObject);
ResourceString
  RaiseStr1 = '没有明细数据，不能进行成批修改操作！';
  RaiseStr2 = '此列数据为只读，不能进行成批修改操作！';
  RaiseStr3 = '输入框';
  RaiseStr4 = '请输入新的[%s]：';
var
  Recno: Integer;
  TmpValue: String;
  TmpCals: TDataSetNotifyEvent;
  TmpDataSet: TDataSet;
begin
  inherited;
  if PMDetailGrid.PopupComponent = nil then
    exit;

  if PMDetailGrid.PopupComponent is TDBGridEh then
  begin
    TmpDataSet := TDBGridEh(PMDetailGrid.PopupComponent).DataSource.DataSet;
    if TmpDataSet.State in dseditmodes then
      TmpDataSet.Post;
    if TmpDataSet.IsEmpty then
      raise Exception.Create(RaiseStr1);
    if TDBGridEh(PMDetailGrid.PopupComponent).SelectedField = nil then
      exit;
    if TDBGridEh(PMDetailGrid.PopupComponent).Columns[TDBGridEh(PMDetailGrid.PopupComponent).SelectedIndex].ReadOnly or
      (TDBGridEh(PMDetailGrid.PopupComponent).SelectedField.FieldKind <> fkData) then
      raise Exception.Create(RaiseStr2);
    if not InputQuery(RaiseStr3, format(RaiseStr4, [TDBGridEh(PMDetailGrid.PopupComponent).SelectedField.DisplayLabel]), TmpValue) then
      exit;
    Recno := TmpDataSet.Recno;
    TmpDataSet.DisableControls;
    TmpCals := TmpDataSet.OnCalcFields;
    TmpDataSet.OnCalcFields := nil;
    TmpDataSet.First;
    try
      While not TmpDataSet.Eof do
      begin
        TmpDataSet.Edit;
        if Assigned(TDBGridEh(PMDetailGrid.PopupComponent).SelectedField.OnSetText) then
          TDBGridEh(PMDetailGrid.PopupComponent).SelectedField.OnSetText(TDBGridEh(PMDetailGrid.PopupComponent).SelectedField, TmpValue);
        TmpDataSet.Edit;
        TDBGridEh(PMDetailGrid.PopupComponent).SelectedField.AsString := TmpValue;
        TmpDataSet.Post;
        TmpDataSet.Next;
      end;
    finally
      TmpDataSet.OnCalcFields := TmpCals;
      TmpDataSet.First;
      TmpDataSet.Recno := Recno;
      TmpDataSet.EnableControls;
    end;
  end;

end;

procedure TfrmAutoMasterDetail.ActPostExecute(Sender: TObject);
var
  newcode: string;
  I: Integer;
  columncount: Integer;
begin
  if strkeyfield = '' then
  begin
    showmessage('系统未设置模块中的【主从关联字段】内容，请与世鸿网络科技联系');
    abort;
  end;

  if FDQryDetail.State in dseditmodes then
    FDQryDetail.Post;

  // 此外不能让主表数据产生滚动操作
  if Assigned(FDQryMaster.AfterScroll) then
  begin
    FDQryMaster.AfterScroll := nil;
  end;
  try

    inherited;

    FDQryDetail.First;
    newcode := FDQryMaster.FieldByName(strkeyfield).AsString;
    while not FDQryDetail.Eof do
    begin
      FDQryDetail.Edit;
      FDQryDetail.FieldByName(strkeyfield).AsString := newcode;
      FDQryDetail.Post;
      FDQryDetail.Next;
    end;
    // 如果是在编辑状态进行保存

    if FDQryDetail.CachedUpdates then
    begin
      FDQryDetail.ApplyUpdates(0);
      FDQryDetail.CommitUpdates;
    end;

  finally
    FDQryMaster.AfterScroll := FDQryMasterAfterScroll;
  end;
end;

procedure TfrmAutoMasterDetail.cxDBButtonEdit1PropertiesButtonClick(Sender: TObject; AButtonIndex: Integer);
var
  curFieldName: String;
begin
  inherited;
  // 在新增修改编辑状态下才可  弹出选择窗口
  if FDQryMaster.State in dseditmodes then
  begin
    // 主表选择内容通用事件
    curFieldName := TcxDBTextEdit(Sender).DataBinding.Field.FieldName;
    // 关联了数据源字段才可进行选择
    if curFieldName <> '' then
    begin
      FDQryModuleFields.Filtered := false;
      if FDQryModuleFields.Locate('MDF_QueryName;MDF_FieldName', vararrayof(['master', curFieldName]), []) then
      begin
        EnterSelectData(FDQryMaster, FDQryModuleFields.FieldByName('MDF_SelectSQL').AsString, FDQryModuleFields.FieldByName('MDF_SelectField').AsString);
      end;
    end;
  end;
end;

procedure TfrmAutoMasterDetail.cxGridDetailDBTableView1Column1PropertiesButtonClick(Sender: TObject; AButtonIndex: Integer);
var
  curGridView: TcxGridDBTableView;
  curFieldName: String;
begin
  inherited;
  // 明细表格按钮 事件
  // TcxGridSite((TcxButtonEdit(Sender).Parent)).ViewInfo.GridView as TcxGridDBTableView
  // ( TcxButtonEdit(Sender).ActiveProperties).Buttons[AButtonIndex].Hint;//取到按钮本身的属性
  // IntToStr( ( TcxGridSite((TcxButtonEdit(Sender).Parent)).ViewInfo.GridView as TcxGridDBTableView).tag);
  // 取到TcxGridDBTableView的属性
  curGridView := TcxGridSite((TcxButtonEdit(Sender).Parent)).ViewInfo.GridView as TcxGridDBTableView;
  // curGridView.Controller.FocusedRowIndex 当前行号
  // curGridView.Controller.FocusedRow 当前行
  // curGridView.Controller.FocusedColumn 当前列
  // curGridView.Controller.FocusedColumnIndex 当前列号
  // curGridView.Controller.EditingItem 当前编辑中的单元框
  // curGridView.Controller.EditingController.Edit 当前的编辑框
  // 在编辑状态下可以这样取当前单元格的值:
  // if curGridView.Controller.FocusedColumn.Editing then
  // ShowMessage(curGridView.Controller.EditingController.Edit.EditingValue)
  // else
  // 非编辑状态下可以这样取得单元格内的值:
  // curGridView.DataController.GetValue(curGridView.DataController.FocusedRecordIndex, curGridView.Controller.FocusedItemIndex);
  curFieldName := TcxGridDBColumn(curGridView.Controller.FocusedColumn).DataBinding.FieldName;
  FDQryModuleFields.Filtered := false;
  if FDQryModuleFields.Locate('MDF_QueryName;MDF_FieldName', vararrayof(['detail', curFieldName]), []) and curGridView.DataController.IsEditing then
  begin
    EnterSelectData(FDQryDetail, FDQryModuleFields.FieldByName('MDF_SelectSQL').AsString, FDQryModuleFields.FieldByName('MDF_SelectField').AsString);
  end;
end;

procedure TfrmAutoMasterDetail.cxGridDetailDBTableView1CustomDrawCell(Sender: TcxCustomGridTableView; ACanvas: TcxCanvas; AViewInfo: TcxGridTableDataCellViewInfo;
  var ADone: Boolean);
begin
  inherited;
  if (AViewInfo.GridRecord.RecordIndex = TcxCustomGridTableView(Sender).Controller.FocusedRecordIndex) then
    exit;
  If (AViewInfo.GridRecord.RecordIndex mod 2) = 1 Then
  Begin
    ACanvas.Brush.Color := clWebHoneydew;
  End;
end;

procedure TfrmAutoMasterDetail.cxGridDetailDBTableView1CustomDrawIndicatorCell(Sender: TcxGridTableView; ACanvas: TcxCanvas; AViewInfo: TcxCustomGridIndicatorItemViewInfo;
  var ADone: Boolean);
var
  FValue: string;
  FBounds: TRect;
begin
  inherited;

  if (AViewInfo is TcxGridIndicatorRowItemViewInfo) then
  begin
    FValue := IntToStr(TcxGridIndicatorRowItemViewInfo(AViewInfo).GridRecord.Index + 1);
    FBounds := AViewInfo.Bounds;
    ACanvas.FillRect(FBounds);
    ACanvas.DrawComplexFrame(FBounds, clBtnHighlight, clBtnShadow, [bBottom, bLeft, bRight], 1);
    InflateRect(FBounds, -1, -1);
    ACanvas.Font.Color := clBlack;
    ACanvas.Brush.Style := bsClear;
    ACanvas.DrawText(FValue, FBounds, cxAlignCenter or cxAlignTop);
    ADone := True;
  end
end;

procedure TfrmAutoMasterDetail.cxGridMasterDBTableView1CustomDrawCell(Sender: TcxCustomGridTableView; ACanvas: TcxCanvas; AViewInfo: TcxGridTableDataCellViewInfo;
  var ADone: Boolean);
begin
  inherited;
  if (AViewInfo.GridRecord.RecordIndex = TcxCustomGridTableView(Sender).Controller.FocusedRecordIndex) then
    exit;
  If (AViewInfo.GridRecord.RecordIndex mod 2) = 1 Then
  Begin
    ACanvas.Brush.Color := clWebHoneydew;
  End;
end;

procedure TfrmAutoMasterDetail.cxGridMasterDBTableView1CustomDrawIndicatorCell(Sender: TcxGridTableView; ACanvas: TcxCanvas; AViewInfo: TcxCustomGridIndicatorItemViewInfo;
  var ADone: Boolean);
begin
  inherited;
  SetRowNumber(Sender, AViewInfo, ACanvas, ADone);
end;

procedure TfrmAutoMasterDetail.cxGridMasterDBTableView1DblClick(Sender: TObject);
begin
  inherited;
  if FDQryMaster.Active and (FDQryMaster.RecordCount > 0) then
    PageControl1.ActivePageIndex := 1;
end;

procedure TfrmAutoMasterDetail.DBGEhMasterDblClick(Sender: TObject);
begin
  inherited;
  if FDQryMaster.Active and (FDQryMaster.RecordCount > 0) then
    PageControl1.ActivePageIndex := 1;
end;

procedure TfrmAutoMasterDetail.dsMasterStateChange(Sender: TObject);
begin
  inherited;
  dsDetail.AutoEdit := FDQryMaster.State in dseditmodes;

end;

procedure TfrmAutoMasterDetail.FDQryDetailNewRecord(DataSet: TDataSet);
var
  I: Integer;
  tmpfield: TField;
begin
  inherited;
  for I := 0 to DataSet.FieldCount - 1 do
  begin
    if (DataSet.Fields[I] is TWideStringField) or (DataSet.Fields[I] is TStringField) or (DataSet.Fields[I] is TByteField) or (DataSet.Fields[I] is TSingleField) or
      (DataSet.Fields[I] is TGuidField) then // 双字节
      DataSet.Fields[I].Value := '';

    // 数值类型
    if ((DataSet.Fields[I] is TNumericField) or (DataSet.Fields[I] is TIntegerField) or (DataSet.Fields[I] is TLongWordField) or (DataSet.Fields[I] is TSmallintField) or
      (DataSet.Fields[I] is TShortintField) or (DataSet.Fields[I] is TWordField) or (DataSet.Fields[I] is TFloatField) or (DataSet.Fields[I] is TLargeintField) or
      (DataSet.Fields[I] is TCurrencyField) or (DataSet.Fields[I] is TExtendedField) or (DataSet.Fields[I] is TBCDField) or (DataSet.Fields[I] is TFMTBCDField)) and
      not(DataSet.Fields[I] is TAutoIncField) and not(DataSet.Fields[I] is TUnsignedAutoIncField) then
      DataSet.Fields[I].Value := 0;

    if DataSet.Fields[I] is TBooleanField then // 布尔类型
      DataSet.Fields[I].asboolean := false;

    if (DataSet.Fields[I] is TDateTimeField) or (DataSet.Fields[I] is TDateField) or (DataSet.Fields[I] is TTimeField) then
      DataSet.Fields[I].AsDateTime := now();

    // TSQLTimeStampField,TSQLTimeStampOffsetField  //时间截
    // TBinaryField，TVarBytesField //二进制数据
    // ,TBlobField ，TMemoField， TWideMemoField， TGraphicField //文件型数据   长文本型数据
    // TObjectField ，TADTField，TArrayField，TDataSetField ，TReferenceField //对象型数据
    // TVariantField
    // TInterfaceField ，TIDispatchField接口型字段
    // TAggregateField
  end;

end;

procedure TfrmAutoMasterDetail.refreshMasterDisplaylabe;
var
  tmpfield: TField;
  I: Integer;
  curComponent: Tcomponent;
  FieldName: string;
  curControl: TWinControl;
  griddbcolumn: TcxGridDBColumn;
begin
  if not FDQryModuleFields.Active then
    FDQryModuleFields.Open();
  FDQryModuleFields.Filtered := false;
  FDQryModuleFields.Filter := 'MDF_Queryname=''master''';
  FDQryModuleFields.Filtered := True;
  FDQryModuleFields.First;
  while not FDQryModuleFields.Eof do
  begin
    tmpfield := FDQryMaster.FindField(FDQryModuleFields.FieldByName('MDF_FieldName').AsString);
    griddbcolumn := cxGridMasterDBTableView1.GetColumnByFieldName(FDQryModuleFields.FieldByName('MDF_FieldName').AsString);
    if Assigned(tmpfield) then
    begin
      tmpfield.DisplayLabel := FDQryModuleFields.FieldByName('MDF_Displaylabel').AsString;
      tmpfield.Visible := FDQryModuleFields.FieldByName('MDF_Display').asboolean;
      tmpfield.Index := I;
      inc(I);

      tmpfield.Tag := 0;
      // lookup 通过查询 只能写入一个内容
      if FDQryModuleFields.FieldByName('MDF_LookupSQL').AsString <> '' then
        tmpfield.Tag := 1;
      // 通过弹出窗口选择值  可以写入多个值 内容
      if FDQryModuleFields.FieldByName('MDF_SelectSQL').AsString <> '' then
        tmpfield.Tag := 2;
    end;

    FDQryModuleFields.Next;
  end;

  FDQryModuleFields.Filtered := false;
  FDQryModuleFields.Filter := 'MDF_Queryname=''detail''';
  FDQryModuleFields.Filtered := True;
  FDQryModuleFields.First;
  I := 0;
  while not FDQryModuleFields.Eof do
  begin
    tmpfield := FDQryDetail.FindField(FDQryModuleFields.FieldByName('MDF_FieldName').AsString);
    if Assigned(tmpfield) then
    begin
      tmpfield.DisplayLabel := FDQryModuleFields.FieldByName('MDF_Displaylabel').AsString;
      tmpfield.Visible := FDQryModuleFields.FieldByName('MDF_Display').asboolean;
      tmpfield.Index := I;
      inc(I);
      tmpfield.Tag := 0;
      // lookup 通过查询 只能写入一个内容
      if FDQryModuleFields.FieldByName('MDF_LookupSQL').AsString <> '' then
        tmpfield.Tag := 1;
      // 通过弹出窗口选择值  可以写入多个值 内容
      if FDQryModuleFields.FieldByName('MDF_SelectSQL').AsString <> '' then
        tmpfield.Tag := 2;

    end;

    FDQryModuleFields.Next;
  end;

  tmpfield := nil;
  // 循环找label组件来修改数据字段显示内容
  // 此处还要判断字段是否存在，不错会出错

end;

procedure TfrmAutoMasterDetail.FDQryMasterAfterScroll(DataSet: TDataSet);
var
  I: Integer;
begin
  inherited;
  FDQryDetail.close;
  for I := 0 to FDQryDetail.Params.Count - 1 do
  begin
    FDQryDetail.Params[I].Value := FDQryMaster.FieldByName(FDQryDetail.Params[I].Name).Value;
  end;
  FDQryDetail.Open;

end;

procedure TfrmAutoMasterDetail.FDQryMasterBeforeDelete(DataSet: TDataSet);
begin
  inherited;
  // 主表内容删除前就删除明细
  if FDQryDetail.State in dseditmodes then
  begin
    FDQryDetail.Cancel;
  end;
  while not FDQryDetail.IsEmpty do
    FDQryDetail.Delete;
  if FDQryDetail.CachedUpdates then
    FDQryDetail.ApplyUpdates;
end;

procedure TfrmAutoMasterDetail.FlowPanel1Resize(Sender: TObject);
begin
  inherited;
  FlowPanel1.AutoSize := True;
  FlowPanel1.AutoSize := false;
end;

procedure TfrmAutoMasterDetail.FormShow(Sender: TObject);
var
  I: Integer;
  tmpfield: TField;
  tmpGridDBColumn: TcxGridDBColumn;
  tmpPanel: TPanel;
  tmplabel: TcxLabel;
  tmpinput: TcxCustomTextEdit;
  tmpcheckbox: TcxCustomCheckBox;
begin
  inherited;
  pnlSearchTool.left := self.width - pnlSearchTool.width - 50;

  // 读取主从数据源固态化字段内容
  FDQryModuleQuery.Filtered := false;
  FDQryModuleQuery.Filter := 'mqy_type=''master''';
  FDQryModuleQuery.Filtered := True;

  if FDQryModuleQuery.RecordCount <> 1 then
  begin
    showmessage('系统后台数据设置错误，请与管理员联系！');
    exit;
  end
  else
  begin
    // FDQryinitialization.close;
    // FDQryinitialization.SQL.Text :='select * from ('+ FDQryModuleQuery.FieldByName('mqy_sql').AsString +') a where 1<>1';
    // FDQryinitialization.Open();
    FDQryMaster.close;
    FDQryMaster.SQL.Text := FDQryModuleQuery.FieldByName('mqy_sql').AsString;
    FDQryMaster.Open();
  end;
  // FDQryMaster.Fields.Clear ;


  // FDQryMaster.CopyFields(FDQryinitialization); // 复制主表动态字段

  FDQryModuleQuery.Filtered := false;
  FDQryModuleQuery.Filter := 'mqy_type=''detail''';
  FDQryModuleQuery.Filtered := True;

  if FDQryModuleQuery.RecordCount <> 1 then
  begin
    showmessage('系统后台数据设置错误，请与管理员联系！');
    exit;
  end
  else
  begin
    // FDQryinitialization.close;
    // FDQryinitialization.SQL.Text := FDQryModuleQuery.FieldByName('mqy_sql').AsString;
    // FDQryinitialization.Open();
    FDQryDetail.close;
    FDQryDetail.SQL.Text := FDQryModuleQuery.FieldByName('mqy_sql').AsString;
    FDQryDetail.Params[0].DataType := ftString;
    FDQryDetail.Open;
  end;

  // FDQryDetail.Fields.Clear ;
  // FDQryDetail.CopyFields(FDQryinitialization); // 复制从表动态字段

  // 主表输入数据源
  FDQryModuleMasterSet.close;
  FDQryModuleMasterSet.ParamByName('mod_code').Value := Name;
  FDQryModuleMasterSet.Open();
  FDQryModuleMasterSet.First;
  while not FDQryModuleMasterSet.Eof do
  begin
    // TcxDBTextEdit   cxDBedit   cxTextEdit
    // TcxDBMemo       cxMeno
    // TcxDBMaskEdit    cxMaskEdit
    // TcxDBButtonEdit  cxButtonEdit
    // TcxDBComboBox ,TcxDBPopupEdit   cxDropDownEdit
    // TcxDBSpinEdit  上下增加数据  cxSpinEdit
    // TcxDBTimeEdit   cxTimeEdit
    // TcxDBBlobEdit   cxBlobEdit
    tmpPanel := TPanel.Create(FlowPanel1);
    tmpPanel.Parent := FlowPanel1;
    tmpPanel.Name := 'Master_pnl_' + FDQryModuleMasterSet.FieldByName('MMS_Fieldname').AsString;
    tmpPanel.Caption := '';
    tmpPanel.Height := 44;
    tmpPanel.AlignWithMargins := True;
    tmpPanel.BevelOuter := bvNone; // 无边线
    if UPPERCASE(FDQryModuleMasterSet.FieldByName('MMS_Type').AsString) <> 'CHECK' then
    begin
      tmplabel := TcxLabel.Create(tmpPanel);
      tmplabel.Parent := tmpPanel;
      tmplabel.Name := 'Master_label_' + FDQryModuleMasterSet.FieldByName('MMS_Fieldname').AsString;
      tmplabel.Caption := FDQryModuleMasterSet.FieldByName('MMS_Displaylabel').AsString;
      tmplabel.Align := altop;
      tmplabel.Transparent := True; // label透明，显示背景底色
    end;
    if UPPERCASE(FDQryModuleMasterSet.FieldByName('MMS_Type').AsString) = 'TEXT' then
    begin
      tmpinput := TcxDBTextEdit.Create(tmpPanel);
      tmpinput.Parent := tmpPanel;
      tmpinput.Name := 'DBedit_' + FDQryModuleMasterSet.FieldByName('MMS_Fieldname').AsString;
      tmpinput.Align := albottom;
      TcxDBTextEdit(tmpinput).DataBinding.DataField := FDQryModuleMasterSet.FieldByName('MMS_Fieldname').AsString;
      TcxDBTextEdit(tmpinput).DataBinding.DataSource := dsMaster;
      if (not FDQryModuleMasterSet.FieldByName('MMS_CanInput').asboolean) or
        (IfAutoNumber and (UPPERCASE(FDQryModuleMasterSet.FieldByName('MMS_Fieldname').AsString) = UPPERCASE(strkeyfield))) then
      begin
        TcxDBTextEdit(tmpinput).Properties.ReadOnly := True;
        TcxDBTextEdit(tmpinput).Style.Color := clInactiveCaption;
      end;
      tmplabel.FocusControl := tmpinput;

    end;
    if UPPERCASE(FDQryModuleMasterSet.FieldByName('MMS_Type').AsString) = 'BUTTON' then
    begin
      tmpinput := TcxDBButtonEdit.Create(tmpPanel);
      tmpinput.Parent := tmpPanel;
      tmpinput.Name := 'DBedit_' + FDQryModuleMasterSet.FieldByName('MMS_Fieldname').AsString;
      tmpinput.Align := albottom;
      TcxDBButtonEdit(tmpinput).DataBinding.DataField := FDQryModuleMasterSet.FieldByName('MMS_Fieldname').AsString;
      TcxDBButtonEdit(tmpinput).DataBinding.DataSource := dsMaster;
      TcxDBButtonEdit(tmpinput).Properties.ReadOnly := not FDQryModuleMasterSet.FieldByName('MMS_CanInput').asboolean;
      TcxDBButtonEdit(tmpinput).Properties.OnButtonClick := cxDBButtonEdit1PropertiesButtonClick;
      if TcxDBButtonEdit(tmpinput).Properties.ReadOnly then
        TcxDBButtonEdit(tmpinput).Style.Color := clInactiveCaption;
      tmplabel.FocusControl := tmpinput;
    end;
    if UPPERCASE(FDQryModuleMasterSet.FieldByName('MMS_Type').AsString) = 'DATE' then
    begin
      tmpinput := TcxDBDateEdit.Create(tmpPanel);
      tmpinput.Parent := tmpPanel;
      tmpinput.Name := 'DBedit_' + FDQryModuleMasterSet.FieldByName('MMS_Fieldname').AsString;
      tmpinput.Align := albottom;
      TcxDBDateEdit(tmpinput).DataBinding.DataField := FDQryModuleMasterSet.FieldByName('MMS_Fieldname').AsString;
      TcxDBDateEdit(tmpinput).DataBinding.DataSource := dsMaster;
      TcxDBDateEdit(tmpinput).Properties.ReadOnly := not FDQryModuleMasterSet.FieldByName('MMS_CanInput').asboolean;
      TcxDBDateEdit(tmpinput).Properties.DisplayFormat := FormatSettings.ShortDateFormat;
      TcxDBDateEdit(tmpinput).Properties.EditFormat := FormatSettings.ShortDateFormat;

      if TcxDBDateEdit(tmpinput).Properties.ReadOnly then
        TcxDBDateEdit(tmpinput).Style.Color := clInactiveCaption;
      tmplabel.FocusControl := tmpinput;
    end;
    if UPPERCASE(FDQryModuleMasterSet.FieldByName('MMS_Type').AsString) = 'CHECK' then
    begin
      tmpcheckbox := TcxDBCheckBox.Create(tmpPanel);
      tmpcheckbox.Parent := tmpPanel;
      tmpcheckbox.Name := 'DBedit_' + FDQryModuleMasterSet.FieldByName('MMS_Fieldname').AsString;
      tmpcheckbox.Align := albottom;
      TcxDBCheckBox(tmpcheckbox).Caption := FDQryModuleMasterSet.FieldByName('MMS_Displaylabel').AsString;
      TcxDBCheckBox(tmpcheckbox).DataBinding.DataField := FDQryModuleMasterSet.FieldByName('MMS_Fieldname').AsString;
      TcxDBCheckBox(tmpcheckbox).DataBinding.DataSource := dsMaster;
      TcxDBCheckBox(tmpcheckbox).Properties.ReadOnly := not FDQryModuleMasterSet.FieldByName('MMS_CanInput').asboolean;
      if TcxDBCheckBox(tmpcheckbox).Properties.ReadOnly then
        TcxDBCheckBox(tmpcheckbox).Style.Color := clInactiveCaption;
      tmplabel.FocusControl := tmpcheckbox;
    end;
    FDQryModuleMasterSet.Next;
  end;

  refreshMasterDisplaylabe();

  (cxGridMasterDBTableView1.DataController as IcxCustomGridDataController).DeleteAllItems; // 删除所有列
  (cxGridMasterDBTableView1.DataController as IcxCustomGridDataController).CreateAllItems(false); // 创建数据源中的所有列
  for I := 0 to cxGridMasterDBTableView1.columncount - 1 do
  begin
    cxGridMasterDBTableView1.Columns[I].HeaderAlignmentHorz := taCenter;
    cxGridMasterDBTableView1.Columns[I].HeaderAlignmentVert := vaCenter;

    if cxGridMasterDBTableView1.Columns[I].width > 300 then
      cxGridMasterDBTableView1.Columns[I].width := 300;
    if cxGridMasterDBTableView1.Columns[I].width < 80 then
      cxGridMasterDBTableView1.Columns[I].width := 80;
  end;

  (cxGridDetailDBTableView1.DataController as IcxCustomGridDataController).DeleteAllItems; // 删除所有列
  (cxGridDetailDBTableView1.DataController as IcxCustomGridDataController).CreateAllItems(false); // 创建数据源中的所有列
  for I := 0 to cxGridDetailDBTableView1.columncount - 1 do
  begin
    cxGridDetailDBTableView1.Columns[I].HeaderAlignmentHorz := taCenter;
    cxGridDetailDBTableView1.Columns[I].HeaderAlignmentVert := vaCenter;

    if cxGridDetailDBTableView1.Columns[I].width > 300 then
      cxGridDetailDBTableView1.Columns[I].width := 300;
    if cxGridDetailDBTableView1.Columns[I].width < 80 then
      cxGridDetailDBTableView1.Columns[I].width := 80;
    // 表格中数据显示方式
    if cxGridDetailDBTableView1.Columns[I].DataBinding.Field is TBooleanField then
      cxGridDetailDBTableView1.Columns[I].PropertiesClass := TcxCheckboxProperties
    else if cxGridDetailDBTableView1.Columns[I].DataBinding.Field.Tag = 2 then
    begin
      // 弹窗选择值
      cxGridDetailDBTableView1.Columns[I].PropertiesClass := TcxButtonEditProperties;
      cxGridDetailDBTableView1.Columns[I].Options.ShowEditButtons := isebAlways;
      TcxButtonEditProperties(cxGridDetailDBTableView1.Columns[I].Properties).Buttons[0].Hint := cxGridDetailDBTableView1.Columns[I].DataBinding.FieldName;
      TcxButtonEditProperties(cxGridDetailDBTableView1.Columns[I].Properties).OnButtonClick := cxGridDetailDBTableView1Column1PropertiesButtonClick;
    end
    else if cxGridDetailDBTableView1.Columns[I].DataBinding.Field.Tag = 1 then
    begin
      // 下拉选择值
      cxGridDetailDBTableView1.Columns[I].Options.ShowEditButtons := isebAlways;
    end;
  end;

  // 快速查找
  if pnlSearchTool.Visible then
    for I := 0 to FDQryMaster.Fields.Count - 1 do
      if (FDQryMaster.Fields[I].FieldKind = fkData) and FDQryMaster.Fields[I].Visible and (Pos('#', FDQryMaster.Fields[I].DisplayLabel) = 0) then
        CmbFindField.Items.AddObject(FDQryMaster.Fields[I].DisplayLabel, FDQryMaster.Fields[I]);
  if CmbFindField.Items.Count > 0 then
    CmbFindField.ItemIndex := 0;
  // CmbFindFieldChange(CmbFindField);
  CmbFindField.left := EdtLocate.left - CmbFindField.width;
  // SBtnSelect.ADDBtnStyle := BS_InRight;
end;

procedure TfrmAutoMasterDetail.GrdDetailEditButtonClick(Sender: TObject);
begin
  inherited;
  if FDQryDetail.IsEmpty then
    FDQryDetail.Append;
end;

procedure TfrmAutoMasterDetail.N4Click(Sender: TObject);
begin
  inherited;
  //
end;

end.
